using System.IO;
using UnityEditor;
using UnityEngine;

namespace Editor
{
    public class Create3DTex : ScriptableObject
    {
        static readonly string SOURCE_PATH = "Assets/Resources/";

        [MenuItem("CustomTools/CreateCloudTexture %#&r")]
        static void CreateAllTexture()
        {
            var CLOUD_PATH = SOURCE_PATH + "/Clouds";
            if (!Directory.Exists(CLOUD_PATH)) return;
            var directoryInfo = new DirectoryInfo(CLOUD_PATH);
            foreach (var directory in directoryInfo.GetDirectories())
            {
                // 获取到目录下的每一个子目录，在子目录下创建3D纹理
                CreateCloudTexture("Clouds/" + directory.Name + "/", false);
                Debug.Log("已创建：" + directory.Name);
            }

            CreateCloudTexture("Noise/", true);
            Debug.Log("3D数据更新生成完毕");
        }

        [MenuItem("CustomTools/CreateCloudTexture", true)]
        static bool Validate()
        {
            return false;
        }


        private static void CreateCloudTexture(string cloudPath, bool isNoise)
        {
            if (!isNoise)
            {
                T2D index, data, w, r, b;
                index.format = TextureFormat.RGB24;
                index.name = "index";
                index.wrapMode = TextureWrapMode.Clamp;
                index.filterMode = FilterMode.Point;
                CreateSource(index, cloudPath);

                data.format = TextureFormat.R8;
                data.name = "data";
                data.wrapMode = TextureWrapMode.Clamp;
                data.filterMode = FilterMode.Bilinear;
                CreateSource(data, cloudPath);

                r.format = TextureFormat.R8;
                r.name = "r";
                r.wrapMode = TextureWrapMode.Clamp;
                r.filterMode = FilterMode.Bilinear;
                CreateSource(r, cloudPath);

                b.format = TextureFormat.RGBA32;
                b.name = "b";
                b.wrapMode = TextureWrapMode.Clamp;
                b.filterMode = FilterMode.Bilinear;
                CreateSource(b, cloudPath);

                w.format = TextureFormat.RGBA32;
                w.name = "w";
                w.wrapMode = TextureWrapMode.Clamp;
                w.filterMode = FilterMode.Bilinear;
                CreateSource(w, cloudPath);
            }
            else
            {
                T2D noise;
                noise.format = TextureFormat.R8;
                noise.name = "noise";
                noise.wrapMode = TextureWrapMode.Repeat;
                noise.filterMode = FilterMode.Bilinear;
                CreateSource(noise, cloudPath);
            }
        }

        /// <summary>
        /// 使用传入的T2D结构体创建3D纹理
        /// </summary>
        /// <param name="t">传入要从要转换为三维数组的T2D结构体</param>
        /// <param name="cloudPath">当前云的存储位置</param>
        static void CreateSource(T2D t, string cloudPath)
        {
            if (!new DirectoryInfo("Assets/Resources/" + cloudPath + t.name).Exists)
            {
                Debug.Log("目录不存在，跳过生成" + cloudPath + t.name);
                return;
            }

            if (new FileInfo("Assets/Resources/" + cloudPath + t.name + ".asset").Exists)
            {
                Debug.Log("纹理存在，跳过生成" + cloudPath + t.name);
                return;
            }

            var tex = Create3DTexture(t.format, t.name, t.wrapMode, t.filterMode, cloudPath);
            AssetDatabase.CreateAsset(tex, "Assets/Resources/" + cloudPath + t.name + ".asset");
        }

        private static Texture3D Create3DTexture(TextureFormat format, string name, TextureWrapMode wrapMode,
            FilterMode filterMode, string cloudPath)
        {
            // 读取图片的Texture2D
            var folderPath = cloudPath + name + "/"; // 格式：Clouds/xxx/index/
            Debug.Log(folderPath);
            var img0 = Resources.Load<Texture2D>(folderPath + name + "1"); // 取index或data中的第一个文件，获取文件尺寸
            var depth = new DirectoryInfo("Assets/Resources/" + folderPath).GetFiles().Length /
                        2; // 取文件总数的一半，还有一半是meta文件
            var width = img0.width;
            var height = img0.height;

            // 创建纹理并应用配置
            var texture = new Texture3D(width, height, depth, format, false)
            {
                wrapMode = wrapMode,
                filterMode = filterMode
            };

            // 创建 3 维数组以存储颜色数据
            var colors = new Color[width * height * depth];

            // 填充数组，使纹理的 x、y 和 z 值映射为红色、蓝色和绿色
            for (int i = 0; i < depth; i++)
            {
                var texPath = folderPath + name + i;
                var tex = Resources.Load<Texture2D>(texPath);
                var texColors = tex.GetPixels(); // colors
                texColors.CopyTo(colors, width * height * i);
            }

            // 将颜色值复制到纹理
            texture.SetPixels(colors);
            // 将更改应用到纹理，然后将更新的纹理上传到 GPU
            texture.Apply();
            return texture;
        }

        private struct T2D
        {
            public TextureFormat format;
            public string name;
            public TextureWrapMode wrapMode;
            public FilterMode filterMode;
        };
    }
}